/*
 * @Descripttion: 
 * @version: 
 * @Author: yuxintao
 * @Date: 2022-04-26 09:14:17
 * @LastEditors: yuxintao
 * @LastEditTime: 2022-04-29 16:16:38
 */
#include "mac.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>//ioctl命令
#include <netinet/if_ether.h>//ethhdr结构
#include <net/if.h>//ifreq结构
#include <netinet/in.h>//in_addr结构
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "mac.h"

#define FIND_IP "192.168.223.1"
#define INTERFACE "ens33"

int fd;
char eth_source[ETH_ALEN] = {0x00, 0x0c, 0x29, 0x06, 0x37, 0x83};
char eth_dest[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
char ef[ETH_FRAME_LEN];
char receive_buf[ETH_FRAME_LEN];

void* receive_thread(void* arg) {
    pthread_detach(pthread_self());
    while (1) {
        memset(receive_buf, 0, sizeof(receive_buf));
        int len = recv(fd, receive_buf, sizeof(receive_buf), 0);
        if (len <= 0) {
            perror("recv");
            exit(1);
        }
        struct ethhdr* p = (struct ethhdr*)receive_buf;
        struct arppacket* p1 = (struct arppacket*)(receive_buf + ETH_HLEN);

        if (p->h_proto != htons(0x806)) continue;

        int find_ip = inet_addr(FIND_IP);
        char * f_ip = (char*)&find_ip;
        if (strncmp(p->h_dest, eth_source, 6) == 0 && p->h_proto == htons(0x0806) 
        && p1->ar_op == htons(2) && strncmp(p1->ar_sip, f_ip, 4) == 0) {        
            struct sockaddr_in tmp;
            tmp.sin_addr.s_addr = *(int*)p1->ar_sip;
            printf("s_ip : %s\t", inet_ntoa(tmp.sin_addr));
            tmp.sin_addr.s_addr = *(int*)p1->ar_tip;
            printf("d_ip : %s\n", inet_ntoa(tmp.sin_addr));
            printf("p->h_proto: 0x%x\t", htons(p->h_proto));
            printf("find_ip:%s mac: 0x", FIND_IP);
            for (int i = 0; i < 6; ++i) {
                printf("%02x ", p1->ar_sha[i]);
            }
            printf("\n");
            fflush(stdout);
        }
    }
}


void arp_request() {
    struct ethhdr* p_ethhdr;
    p_ethhdr = (struct ethhdr*)ef;
    //eth header
    memcpy(p_ethhdr->h_dest, eth_dest, ETH_ALEN);
    memcpy(p_ethhdr->h_source, eth_source, ETH_ALEN);
    p_ethhdr->h_proto = htons(0x0806);//帧类型（arp数据包）
    //arp packet
    struct arppacket* p_arp;
    p_arp = (struct arppacket*)(ef + ETH_HLEN);
    p_arp->ar_hrd = htons(0x1);
    p_arp->ar_pro = htons(0x0800);
    p_arp->ar_hln = 6;
    p_arp->ar_pln = 4;
    p_arp->ar_op = htons(1);
    memcpy(p_arp->ar_sha, eth_source, ETH_ALEN);
    int s_ip = inet_addr("192.168.223.128");
    memcpy(p_arp->ar_sip, (unsigned char*)&s_ip, 4);
    memcpy(p_arp->ar_tha, eth_dest, ETH_ALEN);
    int d_ip = inet_addr(FIND_IP);
    memcpy(p_arp->ar_tip, (unsigned char*)&d_ip, 4);


    struct sockaddr sa;
    bzero(&sa, sizeof(sa));
    sa.sa_family = AF_INET;
    memcpy(sa.sa_data, INTERFACE, strlen(INTERFACE));
    pthread_t tid;
    pthread_create(&tid, NULL, receive_thread, NULL);
    while (1) {
        if (sendto(fd, ef, ETH_FRAME_LEN, 0, &sa, sizeof(sa)) < 0) {
            perror("send");
            exit(0);
        }
        sleep(1);
    }
}

int main() {
    fd = socket(AF_INET, SOCK_PACKET, htons(0x0003));
    if (fd == -1) {
        perror("socket");
        exit(1);
    }
    arp_request();   
    return 0;
}